package com.anuyun.ms.base.filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import com.alibaba.fastjson.JSON;
import com.anuyun.ms.base.auth.TenantUser;
import com.anuyun.ms.base.common.Result;
import com.anuyun.ms.base.config.property.FeatureProperty;
import com.anuyun.ms.base.constant.ResultConstant;
import com.anuyun.ms.base.context.UserContext;
import com.anuyun.ms.base.util.JwtUtil;

@Component
public class AuthFilter implements Filter {
	
	/**
	 * 放行系统路径
	 */
	private static final List<String> SYS_EXCLUDE_URL =  
			Arrays.asList("/swagger-ui.html","/swagger-resources/**","/webjars/**","/v2/**","/");;
	
	/**
	 * 放行的URL 正则匹配
	 */
	private  Set<String> excludeUrlRegex;

	@Autowired
	FeatureProperty featureProperty;
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		getConfigExcludeUrl();
		Filter.super.init(filterConfig);
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;

		String token = request.getHeader("token");

		String url = request.getRequestURI().substring(request.getContextPath().length());
		
		if (isExcludeUrl(url)) {
			chain.doFilter(request, response);
		} else {
			TenantUser user = JwtUtil.unSign(token, TenantUser.class);

			if (null != user) {
				UserContext.LOCAL_TENANT_USER.set(user);

				chain.doFilter(request, response);

				UserContext.LOCAL_TENANT_USER.remove();
			} else {

				String AuthFailedJson = JSON.toJSONString(new Result<>(ResultConstant.E, "登录认证失败"));

				response.setContentType("application/json;charset=UTF-8");
				response.getWriter().write(AuthFailedJson);
				response.getWriter().flush();
				response.getWriter().close();
			}
		}
	}

	@Override
	public void destroy() {
		Filter.super.destroy();
	}
	
	private  void getConfigExcludeUrl() {
		List<String> excludeUrls = new ArrayList<>();
		if(StringUtils.isNotBlank(FeatureProperty.AUTH_EXCLUDE_URL)) {
			excludeUrls  = new ArrayList<>(Arrays.asList(FeatureProperty.AUTH_EXCLUDE_URL.trim().split(",")));
		}
		excludeUrls.addAll(SYS_EXCLUDE_URL);
		this.excludeUrlRegex =  Collections.unmodifiableSet(new HashSet<>(excludeUrls));
	}
	
	
	private boolean isExcludeUrl(String url) {
		AntPathMatcher matcher = new AntPathMatcher();
		for(String s : this.excludeUrlRegex) {
			if(matcher.match(s, url)) {
				return true;
			}
		}
		return false;
	}

}
